jetcrab\bytecode\expressions/
unary.rs1use crate::ast::Node;
2use crate::vm::instructions::Instruction;
3use crate::vm::types::ConstantIndex;
4
5pub trait UnaryGenerator {
6 fn generate_unary_expression(&mut self, node: &Node);
7 fn generate_update_expression(&mut self, node: &Node);
8}
9
10pub trait UnaryCore {
11 fn instructions(&mut self) -> &mut Vec<Instruction>;
12 fn visit_node(&mut self, node: &Node);
13}
14
15impl<T> UnaryGenerator for T
16where
17 T: UnaryCore + crate::bytecode::scope::local_vars::ScopeManager,
18{
19 fn generate_unary_expression(&mut self, node: &Node) {
20 if let Node::UnaryExpression(expr) = node {
21 self.visit_node(&expr.argument);
22 match expr.operator.as_str() {
23 "!" => self.instructions().push(Instruction::Not),
24 "-" => {
25 self.instructions()
26 .push(Instruction::PushConst(ConstantIndex::new(0)));
27 self.instructions().push(Instruction::Sub);
28 }
29 "+" => {}
30 "~" => {
31 self.instructions()
32 .push(Instruction::PushConst(ConstantIndex::new(0)));
33 self.instructions().push(Instruction::Sub);
34 self.instructions().push(Instruction::Inc);
35 }
36 "typeof" => self.instructions().push(Instruction::TypeOf),
37 "void" => {
38 self.instructions().push(Instruction::Pop);
39 self.instructions().push(Instruction::PushUndefined);
40 }
41 "delete" => self.instructions().push(Instruction::Delete),
42 _ => {}
43 }
44 }
45 }
46
47 fn generate_update_expression(&mut self, node: &Node) {
48 if let Node::UpdateExpression(expr) = node {
49 if let Node::Identifier(name) = &*expr.argument {
51 let local_idx = self.get_or_create_local(name);
52
53 self.instructions().push(Instruction::LoadLocal(local_idx));
55
56 match expr.operator.as_str() {
57 "++" => {
58 if expr.prefix {
59 self.instructions().push(Instruction::Inc);
61 self.instructions().push(Instruction::Dup);
62 self.instructions().push(Instruction::StoreLocal(local_idx));
63 } else {
64 self.instructions().push(Instruction::Dup);
66 self.instructions().push(Instruction::Inc);
67 self.instructions().push(Instruction::StoreLocal(local_idx));
68 }
69 }
70 "--" => {
71 if expr.prefix {
72 self.instructions().push(Instruction::Dec);
74 self.instructions().push(Instruction::Dup);
75 self.instructions().push(Instruction::StoreLocal(local_idx));
76 } else {
77 self.instructions().push(Instruction::Dup);
79 self.instructions().push(Instruction::Dec);
80 self.instructions().push(Instruction::StoreLocal(local_idx));
81 }
82 }
83 _ => {
84 self.instructions().push(Instruction::Inc);
85 self.instructions().push(Instruction::StoreLocal(local_idx));
86 }
87 }
88 } else {
89 self.visit_node(&expr.argument);
91 match expr.operator.as_str() {
92 "++" => {
93 if expr.prefix {
94 self.instructions().push(Instruction::Inc);
95 } else {
96 self.instructions().push(Instruction::Dup);
97 self.instructions().push(Instruction::Inc);
98 }
99 }
100 "--" => {
101 if expr.prefix {
102 self.instructions().push(Instruction::Dec);
103 } else {
104 self.instructions().push(Instruction::Dup);
105 self.instructions().push(Instruction::Dec);
106 }
107 }
108 _ => {
109 self.instructions().push(Instruction::Inc);
110 }
111 }
112 }
113 }
114 }
115}